import 'package:json_format/common/models/model.dart';

class ModelOCConvert {
  /// \n
  static String wrap = '\n';

  /// \t
  static String space = "    ";

  static String mClassTxt = "";
  static String mTopClassTxt = "";
  static List<String> objectLis = [];

  static String parseModelV2(InnerModel model, {bool isFirst = false}) {
    String output = '';
    output += wrap;
    // 嵌套的模型
    List<InnerModel> nestModels = [];

    if (model.propertys?.isNotEmpty == true) {
      output += '@interface ${model.name} : NSObject';
      mClassTxt += wrap;
      mClassTxt += '#pragma mark - ${model.name}_Class -';
      mClassTxt += wrap;
      mClassTxt += "@implementation ${model.name}";
      mClassTxt += wrap;
      mClassTxt += '@end';
      mClassTxt += wrap;

      mTopClassTxt += '@class ${model.name}';
      mTopClassTxt += wrap;
      objectLis.add(model.name);
      for (var property in model.propertys!) {
        if (property.subModel != null) {
          nestModels.add(property.subModel!);
        }
        output += wrap;
        String writePro = parsePropertyV2(property);
        output += writePro;
      }
      if (isFirst) {
        output += wrap;
        output += wrap;
        output +=
            '- (instancetype)initWithDictionary:(NSDictionary *)dictionary;';
        output += wrap;
      }
      output += wrap;
      output += '@end';
    } else {}
    if (nestModels.isNotEmpty) {
      for (var model in nestModels) {
        output += wrap;
        output += parseModelV2(model);
        output += wrap;
      }
    }
    return output;
  }

  static String parsePropertyV2(InnerProperty property) {
    String output = '';
    String name = property.name.replaceAll("_", "");
    switch (property.type) {
      case InnerType.bool:
        {
          output += '@property (nonatomic ,assign)BOOL $name;';
        }
        break;
      case InnerType.int:
        {
          output += '@property (nonatomic ,assign)NSInteger $name;';
        }
        break;
      case InnerType.moment:
        {
          output += '@property (nonatomic ,assign)NSString $name;';
        }
        break;
      case InnerType.decimal:
        {
          output += '@property (nonatomic ,assign)CGFloat $name;';
        }
        break;
      case InnerType.string:
        {
          output += '@property (nonatomic ,assign)NSString $name;';
        }
        break;
      case InnerType.list:
        {
          List arr = property.value;
          String nameT = '';
          if (arr.isNotEmpty) {
            String t;
            if (property.subModel != null) {
              t = property.subModel!.name;
            } else {
              t = arr.first.runtimeType.toString();
            }
            switch (t) {
              case "bool":
                {
                  nameT = 'BOOL';
                }
                break;
              case "int":
                {
                  nameT = 'NSInteger';
                }
                break;
              case "moment":
                {
                  nameT = 'NSString';
                }
                break;
              case "decimal":
                {
                  nameT = 'CGFloat';
                }
                break;
              case "String":
                {
                  nameT = 'NSString';
                }
                break;
              default:
                nameT = t;
                break;
            }
            output += '@property (nonatomic ,copy)NSArray<$nameT *> * $name;';
          } else {
            output +=
                '@property (nonatomic ,copy)NSArray<AnyObject *> * $name;';
          }
        }
        break;
      case InnerType.object:
        {
          InnerModel model = property.value;
          if (model.propertys?.isNotEmpty == true) {
            output += '@property (nonatomic ,copy)${model.name} * $name;';
          } else {
            output += '@property (nonatomic ,assign)AnyObject * $name;';
          }
        }
        break;
      case InnerType.nil:
        {
          output += '@property (nonatomic ,assign)AnyObject $name;';
        }
        break;
      default:
        break;
    }
    return output;
  }

  static String parseModelH(InnerModel model) {
    String output = '';
    output += wrap;
    output += '#import "${model.name}.h';
    output += wrap;
    output += mClassTxt;
    output += wrap;
    output += wrap;
    output += "- (instancetype)initWithDictionary:(NSDictionary *)dictionary {";
    output += wrap;
    output += "${space + space}self = [super init];";
    output += wrap;
    output += "${space + space}if (self) {";
    output += wrap;
    output +=
        "${space + space}${space + space}[self parseFromDictionary:dictionary];";
    output += wrap;
    output += "${space + space}}";
    output += wrap;
    output += "${space + space}return self;";
    output += wrap;
    output += "}";
    output += wrap;
    output += wrap;

    output += "- (void)parseFromDictionary:(NSDictionary *)dictionary {";
    output += wrap;
    for (var property in model.propertys!) {
      print("property ${property.name}");
      output += parsePropertyChild("self", property);
    }
    output += "}";
    output += wrap;
    output += "@end";

    return output;
  }

  static String parsePropertyChild(String rootName, InnerProperty property) {
    String output = '';
    String name = property.name.replaceAll("_", "");
    switch (property.type) {
      case InnerType.list:
        List arr = property.value;
        String nameT = '';

        output += wrap;
        output += wrap;
        output += "${space + space}//解析语言数组";
        if (arr.isNotEmpty) {
          dynamic first = arr.first;
          String t;
          if (property.subModel != null) {
            t = property.subModel!.name;
          } else {
            t = arr.first.runtimeType.toString();
          }
          dynamic inner = first;
          while (inner is List) {
            if (inner.isNotEmpty) {
              inner = inner.first;
            }
          }
          if (first is InnerModel) {
            if (first.propertys?.isNotEmpty == true) {
              output += wrap;
              output +=
                  """${space + space}NSArray *${name}Array = dictionary[@"$name"];""";
              output += wrap;
              output +=
                  """${space + space}NSMutableArray<${capitalize(name)} *> *$name = [NSMutableArray array];""";
              output += wrap;
              output +=
                  """${space + space}for (NSDictionary *${name}Dict in ${name}Array) {""";
              output += wrap;
              output +=
                  """${space + space}${space + space}${capitalize(name)} *${name}s = [[${capitalize(name)} alloc] init];""";
              for (var property in first.propertys!) {
                output += parsePropertyChild("${space + space}$name", property);
              }
              output += wrap;
              output +=
                  """${space + space}${space + space}[${name}s addObject:${name}];""";
              output += wrap;
              output += """${space + space}}""";
              output += wrap;
              output +=
                  """${space + space}$rootName.${name} = [${name}s copy];""";
            }
          } else {
            output += wrap;
            output +=
                """${space + space}$rootName.$name = dictionary[@"$name"];""";
          }
        } else {
          output += wrap;
          output +=
              """${space + space}$rootName.$name = dictionary[@"$name"];""";
        }
        break;
      case InnerType.object:
        {
          InnerModel model = property.value;
          output += wrap;
          output += wrap;
          output += "${space + space}// 解析嵌套的对象";
          output += wrap;
          output +=
              """${space + space}NSDictionary *${name}Dict = dictionary[@"$name"];""";
          if (model.propertys?.isNotEmpty == true) {
            for (var property in model.propertys!) {
              output += parsePropertyChild(name, property);
            }
          }
        }
        break;
      default:
        output += wrap;
        output += """${space + space}$rootName.$name = dictionary[@"$name"];""";
        break;
    }
    return output;
  }

  static String capitalize(String str) {
    if (str.isEmpty) {
      return str;
    }
    return str[0].toUpperCase() + str.substring(1);
  }
}
